package com.mall.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.zxing.WriterException;
import com.mall.common.Constant;
import com.mall.exception.MallException;
import com.mall.exception.MallExceptionEnum;
import com.mall.filter.UserFilter;
import com.mall.mapper.CartMapper;
import com.mall.mapper.OrderItemMapper;
import com.mall.mapper.OrderMapper;
import com.mall.mapper.ProductMapper;
import com.mall.model.dto.CreateOrderRequest;
import com.mall.model.po.Order;
import com.mall.model.po.OrderExample;
import com.mall.model.po.OrderItem;
import com.mall.model.po.Product;
import com.mall.model.vo.CartVo;
import com.mall.model.vo.OrderItemVo;
import com.mall.model.vo.OrderVo;
import com.mall.service.CartService;
import com.mall.service.OrderService;
import com.mall.utils.OrderCodeFactory;
import com.mall.utils.QRCodeGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private CartService cartService;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private CartMapper cartMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Value("${upload-dir}")
    private String dir;
//生成订单
    @Override
    @Transactional(propagation= Propagation.REQUIRES_NEW,isolation= Isolation.READ_COMMITTED,timeout = -1,readOnly = false,noRollbackFor=Exception.class)
    public String createOrder(Integer userId, CreateOrderRequest createOrderRequest) {
        //1.获得购物车已经勾选的数据
//        获取所有的购物车vo信息
        List<CartVo> cartVoList = cartService.list(userId);
//        获取所有被选中的购物车信息
        List<CartVo> tempList = new ArrayList<CartVo>();
//        遍历所有的购物车信息
        for (CartVo cartVo : cartVoList) {
//            判断商品是否被选中
            if (cartVo.getSelected().equals(Constant.CartSelected.SELECTED)) {
                tempList.add(cartVo);
            }
        }
//        让cartVolist 成为所有被选中的商品信息
        cartVoList = tempList;

        //2.校验购物车数据
//        判断当购物车为空时
        if (CollectionUtils.isEmpty(cartVoList)) {
            throw new MallException(MallExceptionEnum.CART_IS_EMPTY);
        }
        //3.数据校验
        validSelectedCarts(cartVoList);
        //4.将购物车对象转为订单项对象
        List<OrderItem> orderItemList = cartVoListToOrderItemList(cartVoList);
        //5.扣库存
        delStock(orderItemList);
        //6.清除已经选中的购物车数据
        clearCartSelected(cartVoList);
//       7.生成订单
//        生成唯一的订单编号
        String orderNo = OrderCodeFactory.getOrderCode(userId.longValue());
        Order order = new Order();
//        将信息传到order对象中
        order.setOrderNo(orderNo);
        order.setOrderStatus(Constant.OrderStatusEnum.NOT_PAID.getCode());
        order.setPaymentType(1);
        order.setPostage(0);
        order.setReceiverAddress(createOrderRequest.getReceiverAddress());
        order.setReceiverMobile(createOrderRequest.getReceiverMobile());
        order.setReceiverName(createOrderRequest.getReceiverName());
        order.setUserId(userId);
        order.setTotalPrice(getOrderTotalPrice(orderItemList));
        orderMapper.insertSelective(order);
        //8.插入订单项数据保存到数据库
        for (OrderItem orderItem : orderItemList) {
            orderItem.setOrderNo(orderNo);
            orderItemMapper.insertSelective(orderItem);
        }
        return orderNo;


    }

    //校验购物车数据
    private void validSelectedCarts(List<CartVo> cartVoList) {
//        遍历购物车数据是否合法
        for (CartVo cartVo :
                cartVoList) {
            Product product = productMapper.selectByPrimaryKey(cartVo.getProductId());
            if (product == null || product.getStatus().equals(Constant.SellStatus.NOT_SELL)) {
                throw new MallException(MallExceptionEnum.NOT_EXIST_PRODUCT);
            }
            if (product.getStock() < cartVo.getQuantity()) {
                throw new MallException(MallExceptionEnum.NEED_STOCK);
            }
        }
    }

    //将购物车数据转为订单项数据
    private List<OrderItem> cartVoListToOrderItemList(List<CartVo> cartVoList) {
        List<OrderItem> orderItemList = new ArrayList<OrderItem>();
        for (CartVo cartVo : cartVoList) {
            OrderItem orderItem = new OrderItem();
            orderItem.setProductId(cartVo.getProductId());
            orderItem.setQuantity(cartVo.getQuantity());
            orderItem.setTotalPrice(cartVo.getTotalPrice());
            orderItem.setProductImg(cartVo.getProductImage());
            orderItem.setProductName(cartVo.getProductName());
            orderItem.setUnitPrice(cartVo.getPrice());
            orderItemList.add(orderItem);
        }
        return orderItemList;
    }

    //扣库存
    private void delStock(List<OrderItem> orderItemList) {
//        在选中列表中遍历减去库存
        for (OrderItem orderItem : orderItemList) {
            Product product = productMapper.selectByPrimaryKey(orderItem.getProductId());
            if (product.getStock() < orderItem.getQuantity()) {
                throw new MallException(MallExceptionEnum.NEED_STOCK);
            }
            product.setStock(product.getStock() - orderItem.getQuantity());
            productMapper.updateByPrimaryKeySelective(product);
        }
    }

    //清理购物车数据
    private void clearCartSelected(List<CartVo> cartVoList) {
//        在选中的购物车商品列表中遍历删除
        for (CartVo cartVo : cartVoList) {
            cartMapper.deleteByPrimaryKey(cartVo.getId());
        }
    }

    //计算订单总价
    private Integer getOrderTotalPrice(List<OrderItem> orderItemList) {
        int orderTotal = 0;
        for (OrderItem orderItem : orderItemList) {
            orderTotal += orderItem.getTotalPrice();
        }
        return orderTotal;
    }
//订单详情
    @Override
    public OrderVo detail(String orderNo) {
//        先查询有无订单
        Order order = orderMapper.selectOrderByOrderNo(orderNo);
        if (order == null) {
            throw new MallException(MallExceptionEnum.NOT_EXIST_ORDER);
        }
        if (!order.getUserId().equals(UserFilter.currentUser.getId())) {
            throw new MallException(MallExceptionEnum.NOT_YOUR_ORDER);
        }
        OrderVo orderVo = orderToOrderVo(order);
        return orderVo;
    }

    private OrderVo orderToOrderVo(Order order) {
//        将订单转化成订单vo
        OrderVo orderVo = new OrderVo();
        BeanUtils.copyProperties(order, orderVo);
        List<OrderItemVo> orderItemVoList = new ArrayList<OrderItemVo>();
//        查询订单项的数据
        List<OrderItem> orderItemList = orderItemMapper.selectByOrderNo(order.getOrderNo());
//        将订单项的数据遍历到订单vo中
        for (OrderItem orderItem : orderItemList
        ) {
            OrderItemVo orderItemVo = new OrderItemVo();
            BeanUtils.copyProperties(orderItem, orderItemVo);
            orderItemVoList.add(orderItemVo);
        }
        orderVo.setOrderItemVOList(orderItemVoList);
        return orderVo;
    }
//前台订单列表
    @Override
    public PageInfo listForCustomer(Integer pageNum, Integer pageSize, Integer userId) {
        //开启分页
        PageHelper.startPage(pageNum, pageSize, "create_time desc");
        //根据用户id查询订单列表
        OrderExample example = new OrderExample();
        example.createCriteria().andUserIdEqualTo(userId);
        List<Order> orders = orderMapper.selectByExample(example);
        //将订单列表转为订单vo列表
        List<OrderVo> orderVoList = orderListToOrderVoList(orders);
        PageInfo pageInfo = new PageInfo(orders);
        //将分页数据替换成orderVoList
        pageInfo.setList(orderVoList);
        return pageInfo;
    }

    private List<OrderVo> orderListToOrderVoList(List<Order> orders) {
        List<OrderVo> list = new ArrayList();
        for (Order order : orders) {
            OrderVo orderVo = orderToOrderVo(order);
            list.add(orderVo);
        }
        return list;
    }
//取消订单
    @Override
    public void cancel(String orderNo) {
//        通过订单号查找订单
        Order order = orderMapper.selectOrderByOrderNo(orderNo);
//        校验数据
//    判断订单是否为空
        if (order == null) {
            throw new MallException(MallExceptionEnum.NOT_EXIST_ORDER);
        }
//        判断订单是否是当前用户的
        if (!order.getUserId().equals(UserFilter.currentUser.getId())) {
            throw new MallException(MallExceptionEnum.NOT_YOUR_ORDER);
        }
//        判断订单是否处于待支付状态
        if (!order.getOrderStatus().equals(Constant.OrderStatusEnum.NOT_PAID.getCode())) {
            throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
        } else {
            Order o = new Order();
            o.setId(order.getId());
            o.setOrderNo(orderNo);
            o.setOrderStatus(Constant.OrderStatusEnum.CANCELED.getCode());
            o.setEndTime(new Date());
            orderMapper.updateByPrimaryKeySelective(o);
        }
    }
//生成支付二维码
    @Override
    public String qrcode(String orderNo) {
//        查询有无此订单
        Order order = orderMapper.selectOrderByOrderNo(orderNo);
        String QrPng = createQRCodeByOrder(order);
        pay(orderNo);
        return QrPng;
    }
    private String createQRCodeByOrder(Order order) {
        try {
            QRCodeGenerator.generateQRCodeImage("http://支付路径",350,350,dir+"temp.png");
        } catch (WriterException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "http://127.0.0.1/images/temp.png";
    }
//支付操作
@Override
public void pay(String orderNo) {
    //通过订单号查找订单
    Order order = orderMapper.selectOrderByOrderNo(orderNo);
    //校验数据
    if(order==null){
        throw new MallException(MallExceptionEnum.NOT_EXIST_ORDER);
    }
    if(!order.getUserId().equals(UserFilter.currentUser.getId())){
        throw new MallException(MallExceptionEnum.NOT_YOUR_ORDER);
    }
//    订单处于待支付状态
    if(order.getOrderStatus().equals(Constant.OrderStatusEnum.NOT_PAID.getCode())){
//        将修改数据存到对象中并修改订单表
        Order o = new Order();
        o.setId(order.getId());
        o.setOrderNo(orderNo);
        o.setOrderStatus(Constant.OrderStatusEnum.PAID.getCode());
        o.setPayTime(new Date());
        orderMapper.updateByPrimaryKeySelective(o);
    } else {
        throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
    }
}
//后台获取订单列表
@Override
public PageInfo listForAdmin(Integer pageNum, Integer pageSize) {
    //开启分页
    PageHelper.startPage(pageNum,pageSize,"update_time desc");
    List<Order> orders = orderMapper.selectByExample(null);
    //将订单列表转为订单vo列表
    List<OrderVo> orderVoList = orderListToOrderVoList(orders);
    PageInfo pageInfo = new PageInfo(orders);
    //将分页数据替换成orderVoList
    pageInfo.setList(orderVoList);
    return pageInfo;
}
//发货
@Override
public void deliver(String orderNo) {
    //根据订单编号查询订单
    Order order = orderMapper.selectOrderByOrderNo(orderNo);
//    判断
    if(order==null){
        throw new MallException(MallExceptionEnum.NOT_EXIST_ORDER);
    }
    if(order.getOrderStatus().equals(Constant.OrderStatusEnum.PAID.getCode())){
        Order o = new Order();
        o.setId(order.getId());
        o.setOrderNo(orderNo);
        o.setOrderStatus(Constant.OrderStatusEnum.DELIVERED.getCode());
        o.setDeliveryTime(new Date());
        orderMapper.updateByPrimaryKeySelective(o);
    }else {
        throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
    }
}
//确认收货
    @Override
    public void finish(String orderNo) {
        Order order = orderMapper.selectOrderByOrderNo(orderNo);
        if(order==null){
            throw  new MallException(MallExceptionEnum.NOT_EXIST_ORDER);
        }
        if(UserFilter.currentUser.getRole().equals(Constant.User.IS_USER) && !UserFilter.currentUser.getId().equals(order.getUserId())){
            throw  new MallException(MallExceptionEnum.NOT_YOUR_ORDER);
        }
        if(order.getOrderStatus().equals(Constant.OrderStatusEnum.DELIVERED.getCode())){
            Order o = new Order();
            o.setId(order.getId());
            o.setOrderNo(orderNo);
            o.setOrderStatus(Constant.OrderStatusEnum.FINISHED.getCode());
            o.setEndTime(new Date());
            orderMapper.updateByPrimaryKeySelective(o);
        }else {
            throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
        }
    }
}
